﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GcmpModelInterface.h"
#include "INoElementIdDbObject.h"
#include "GcmpApiDeclaration.h"

namespace gcmp
{
    class IModelView;
    class UniIdentity;
    enum class GraphicsNodeVisibility;

    /// \brief 图形样式重载级别
    enum class GraphicsStyleOverrideGrade : int8_t
    {
        Document = 0,   ///< 文档级，在所有视图中有效
        ModelView = 1   ///< 视图级，在当前视图中有效，且覆盖文档级
    };

    /// \brief 图形样式有效范围
    enum class GraphicsStyleActiveRange : int8_t
    {
        Background = 0, ///< 背景样式
        Foreground = 1  ///< 前景样式
    };

  

    /// \brief 图形节点样式和材质的重载定制器,用户派生使用
    class GCMP_MODEL_INTERFACE_EXPORT IGraphicsNodeStyleAndMaterialCustomizer : public INoElementIdDbObject
    {
        DEFINE_CAST_DERIVED(gcmp::IGraphicsNodeStyleAndMaterialCustomizer, gcmp::INoElementIdDbObject)
    public:
        /// 目前支持视图、文档级样式——element级别的自定义重载
        class GCMP_MODEL_INTERFACE_EXPORT CustomizationInfo
        {
        public:
            /// \brief样式名称定制样式
            /// \param grade 自定义重载的级别
            /// \param oldStyleName 样式名称
            /// \param newStyleId 自定义重载的样式Id
            void CustomizeElementGraphicsStyleByStyleName(GraphicsStyleOverrideGrade grade, const std::wstring& oldStyleName, const ElementId& newStyleId);
            
            /// \brief样式Uid定制样式
            /// \param grade 自定义重载的级别
            /// \param oldStyleTargetCategoryUid 样式Uid
            /// \param newStyleId 自定义重载的样式Id
            void CustomizeElementGraphicsStyleByTargetCategoryUid(GraphicsStyleOverrideGrade grade, const UniIdentity& oldStyleTargetCategoryUid, const ElementId& newStyleId);

            /// \brief根据样式名称获取定制样式
            /// \param grade 自定义重载的级别
            /// \return 名称定制的样式
            const std::map<std::wstring, ElementId>& GetCustomizedElementGraphicsStylesByStyleNames(GraphicsStyleOverrideGrade grade) const;

            /// \brief根据样式Uid获取定制样式
            /// \param grade 自定义重载的级别
            /// \return Uid定制的样式
            const std::map<gcmp::UniIdentity, ElementId>& GetCustomizedElementGraphicsStylesByTargetCategoryUids(GraphicsStyleOverrideGrade grade) const;

            /// \brief样式名称定制可见性
            /// \param styleName 样式名称
            /// \param visibility 可见性类型
            void CustomizeElementVisibilityByStyleName(const std::wstring& styleName, const gcmp::GraphicsNodeVisibility& visibility);

            /// \brief样式Uid定制可见性
            /// \param oldStyleTargetCategoryUid 样式Uid
            /// \param visibility 可见性类型
            void CustomizeElementVisibilityByTargetCategoryUid(const UniIdentity& styleTargetCategoryUid, const GraphicsNodeVisibility& visibility);

            /// \brief根据样式名称获取定制可见性
            /// \return 名称定制的可见性
            const std::map<std::wstring, GraphicsNodeVisibility>& GetCustomizedElementVisibilitiesByStyleNames() const;

            /// \brief根据样式Uid获取定制可见性
            /// \return Uid定制的可见性
            const std::map<gcmp::UniIdentity, GraphicsNodeVisibility>& GetCustomizedElementVisibilitiesByTargetCategoryUids() const;

            /// \brief根据图形样式重载等级、有效范围，设定自定义的的styleIds
            /// \param grade 自定义重载的级别
            /// \param range 自定义重载的作用范围
            /// \param styleIds 自定义重载的一组样式elementId 注意：排在前面的样式比排在后面的样式优先级高
            void CustomizeElementGraphicsStyle(GraphicsStyleOverrideGrade grade, GraphicsStyleActiveRange range, const std::vector<ElementId>& styleIds);

            /// \brief获取自定义样式重载相关信息
            /// 具体规则和设计文档可参见https://km.glodon.com/pages/viewpage.action?pageId=241729722
            /// \param grade 自定义重载的级别
            /// \param range 自定义重载的作用范围
            /// \param[out] isCustomized 是否自定义重载，平台内部调用。返回true，则这一优先级使用用户自定义的，返回false，则用平台默认的。
            /// \param[out] styleIds 自定义重载的一组样式elementId；isCustomized为true时使用，若styleIds无效，略过这一优先级，为true则使用。
            void GetCustomizedElementGraphicsStyle(GraphicsStyleOverrideGrade grade, GraphicsStyleActiveRange range, bool& isCustomized, std::vector<ElementId>& styleIds) const;

        private:
            class ElementGraphicsStyleOrMaterialInfo
            {
            public:
                ElementGraphicsStyleOrMaterialInfo();
                void SetId(const std::vector<ElementId>& ids);
                void GetId(bool& isCustomized, std::vector<ElementId>& ids) const;
            private:
                bool m_isCustomized = false;
                std::vector<ElementId> m_styleOrMaterialIds;
            };

            //数据源同原GraphicsOverrideBuffer之StyleId
            class GraphicsOverrideStyleIdCustomization
            {
            public:
                GraphicsOverrideStyleIdCustomization();
            public:
                void SetNameToStyleId(const std::wstring& name, const ElementId& styleId);
                void SetUniIdentityToStyleId(const gcmp::UniIdentity& uniIdentity, const ElementId& styleId);
                const std::map<std::wstring, ElementId>& GetNameToStyleIdMap() const;
                const std::map<gcmp::UniIdentity, ElementId>& GetCategoryToStyleIdMap() const;
            private:
                std::map<std::wstring, ElementId> m_nameToStyleIdMap;
                std::map<gcmp::UniIdentity, ElementId> m_categoryUidToStyleIdMap;
            };

            //数据源同原GraphicsOverrideBuffer之Visiblity
            class GraphicsOverrideVisiblityCustomization
            {
            public:
                GraphicsOverrideVisiblityCustomization();
            public:
                void SetNameToVisibility(const std::wstring& name, const GraphicsNodeVisibility& visiblity);
                void SetUniIdentityToVisibility(const gcmp::UniIdentity& uniIdentity, const GraphicsNodeVisibility& visiblity);
                const std::map<std::wstring, GraphicsNodeVisibility>& GetNameToVisibilityMap() const;
                const std::map<gcmp::UniIdentity, GraphicsNodeVisibility>& GetCategoryToVisibilityMap() const;
            private:
                std::map<std::wstring, GraphicsNodeVisibility> m_nameToVisiblityMap;
                std::map<gcmp::UniIdentity, GraphicsNodeVisibility> m_categoryUidToVisiblityMap;
            };
            
        private:
            ElementGraphicsStyleOrMaterialInfo m_elementCustomizationInfo[2][2];
            GraphicsOverrideStyleIdCustomization m_graphicsOverrideBufferCustomization[2];
            GraphicsOverrideVisiblityCustomization m_graphicsOverrideVisiblityCustomization;
        };

    public: 
        /// \brief 平台通过此接口获取用户提供的样式及材质的重载信息
        /// \param pModelView 当前渲染场景对应的modelview
        /// \return CustomizationInfo 重载信息
        virtual CustomizationInfo GetCustomizationInfo(const IModelView* pModelView) const = 0;    
    };
}
